﻿using Ganweisoft.IoTCenter.Module.MediaPlatform.Models;
using Ganweisoft.IoTCenter.Module.MediaPlatform.Utilities;
using IoTCenter.Utilities;
using IoTCenter.Utilities.Extensions;
using IoTCenter.Utilities.Models;
using Microsoft.Extensions.Logging;
using Onvif.WebApi.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Onvif.WebApi.ServicesImpl
{
    public class OnvifService : IOnvifService
    {
        private readonly ILogger<OnvifService> _logger;

        private readonly IUdpClientService _udpClientService;
        private readonly IOnvifDeviceRequestProxy _onvifDeviceRequestProxy;
        //private readonly IDevicesManageService _devicesManageService;
        //private readonly IStreamsManageService _streamsManageService;
        //private readonly IDevicesStreamManageService _devicesStreamManageService;
        //private readonly IStreamOutputTemplatesService _streamOutputTemplatesService;

        public OnvifService(
            ILoggerFactory loggerFactory,
            IUdpClientService udpClientService,
            IOnvifDeviceRequestProxy onvifDeviceRequestProxy
            //IDevicesManageService devicesManageService,
            //IStreamsManageService streamsManageService,
            //IDevicesStreamManageService devicesStreamManageService,
            //IStreamOutputTemplatesService streamOutputTemplatesService
            )
        {
            _udpClientService = udpClientService;
            _onvifDeviceRequestProxy = onvifDeviceRequestProxy;
            _logger = loggerFactory.CreateLogger<OnvifService>();

            //_streamsManageService = streamsManageService;
            //_devicesManageService = devicesManageService;
            //_devicesStreamManageService = devicesStreamManageService;
            //_streamOutputTemplatesService = streamOutputTemplatesService;
        }

        public async Task<IEnumerable<OnvifDeviceListResponseModel>> DeviceDiscoverAsync(OnvifDeviceListRequestModel request)
        {
            if (request == null || request.LocalIP.IsEmpty() || request.RemoteIP.IsEmpty())
            {
                return Enumerable.Empty<OnvifDeviceListResponseModel>();
            }

            var udpClient = _udpClientService.GetUdpClient(request.LocalIP);
            if (udpClient == null)
            {
                return Enumerable.Empty<OnvifDeviceListResponseModel>();
            }

            var cancellationToken = new CancellationTokenSource();
            using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(request.Timeout));
            using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken.Token, timeoutCts.Token);

            var messageId = Guid.NewGuid().ToString();

            try
            {
                var probeTask = _udpClientService.SendProbeMessages(udpClient, request.RemoteIP, messageId);
                var discoverMessagesTask = _udpClientService.ReceiveDiscoverMessages(udpClient, messageId, cts.Token);

                await Task.WhenAll(probeTask, discoverMessagesTask);

                var discoverDevices = discoverMessagesTask.Result;
                if (discoverDevices.IsEmpty())
                {
                    return Enumerable.Empty<OnvifDeviceListResponseModel>();
                }

                // 数据过滤，不要重复新增数据
                // 类型
                // 是可以勾选

                return discoverDevices.Select(x => new OnvifDeviceListResponseModel()
                {
                    Brand = x.Mfr,
                    Model = x.Model,
                    Ip = x.Address
                });
            }
            catch (Exception ex)
            {
                // Console.WriteLine(ex.Message);
                _logger.LogError(ex, "Onvif设备发现异常");
            }
            finally
            {
                udpClient.Close();
            }

            return Enumerable.Empty<OnvifDeviceListResponseModel>();
        }

        public async Task<OperateResult<IEnumerable<int>>> CreateDeviceAsync(OnvifDeviceCreateRequestModel request)
        {
            if (request == null)
            {
                return OperateResult.Failed<IEnumerable<int>>(4001, "参数错误");
            }

            if (request.UserName.IsEmpty())
            {
                return OperateResult.Failed<IEnumerable<int>>(4002, "参数错误");
            }

            if (request.Password.IsEmpty())
            {
                return OperateResult.Failed<IEnumerable<int>>(4003, "参数错误");
            }

            if (request.DeviceIps.IsEmpty())
            {
                return OperateResult.Failed<IEnumerable<int>>(4004, "参数错误");
            }
            else
            {
                if (!request.DeviceIps.All(x => x.IsIp()))
                {
                    return OperateResult.Failed<IEnumerable<int>>(4005, "参数错误");
                }
            }

            var deviceCreateRequests = await GetOnvifDevicesCreateRequest(request);
            if (deviceCreateRequests.IsEmpty())
            {
                return OperateResult.Failed<IEnumerable<int>>(4006, "参数错误");
            }

            IEnumerable<int> results = new List<int>();

            /*
            var config = await _streamOutputTemplatesService.GetStreamOutputTemplateAvailableData();
            if (config == null)
            {
                return OperateResult.Failed<IEnumerable<int>>(4007, message: "视频流模板未配置！");
            }

            foreach (var createRequest in deviceCreateRequests)
            {
                // 新建设备
                var createResult = await _devicesManageService.CreateDeviceAsync(createRequest.DeviceCreateRequest);
                if (!createResult.Succeeded)
                {
                    continue;
                }

                var deviceId = createResult.Data;

                // 新建设备对接方式
                createRequest.DeviceConfigCreateRequest.DeviceId = deviceId;
                createResult = await _devicesStreamManageService.CreateDeviceStreamsConfigs(createRequest.DeviceConfigCreateRequest);
                if (!createResult.Succeeded)
                {
                    continue;
                }

                // 新增设备拉流
                var deviceStreamConfigId = createResult.Data;
                if (createRequest.DeviceStreamUrls.HasValues())
                {
                    foreach (var streamUrl in createRequest.DeviceStreamUrls)
                    {
                        var streamCreateRequest = new StreamCreateRequestModel()
                        {
                            DeviceId = deviceId,
                            DeviceStreamConfigId = deviceStreamConfigId,
                            ConfigId = config.Id,
                            App = "app",
                            Host = "host",
                            Enabled = true,
                            IsCreateOriginalStream = true,
                            Name = $"rtsp_pull",
                            StreamId = $"{deviceId}{deviceStreamConfigId}{config.Id}_pull",
                            UrlPath = streamUrl
                        };

                        var result = await _streamsManageService.CreateStreams(streamCreateRequest);
                    }
                }
            }
            */

            return OperateResult.Successed(results);
        }

        private async Task<IEnumerable<OnvifDeviceCreateItemModel>> GetOnvifDevicesCreateRequest(OnvifDeviceCreateRequestModel request)
        {
            var results = new List<OnvifDeviceCreateItemModel>();
            foreach (var deviceIp in request.DeviceIps)
            {
                var discoverRequest = new OnvifDeviceListRequestModel()
                {
                    LocalIP = request.LocalIP,
                    Timeout = 2,
                    RemoteIP = deviceIp
                };

                var devices = await DeviceDiscoverAsync(discoverRequest);
                if (devices.IsEmpty())
                {
                    continue;
                }
                var device = devices.First();

                // Console.WriteLine($"品牌：{device.Brand}\r\n型号：{device.Model}\r\nIp:{device.Ip}");
                _logger.LogWarning($"===============设备信息===============\r\n品牌：{device.Brand}\r\n型号：{device.Model}\r\nIp:{device.Ip}");

                var result = new OnvifDeviceCreateItemModel()
                {
                    DeviceCreateRequest = new DeviceCreateRequestModel()
                    {
                        Name = device.Ip,
                        Brand = device.Brand,
                        Model = device.Model,
                        Ip = deviceIp,
                        Type = DeviceTypes.IPC,
                        GroupId = 1,
                        Sort = 1,
                        Ipc = new CreateIPCModel() { }
                    },
                    DeviceConfigCreateRequest = new DeviceStreamCreateRequestModel()
                    {
                        Protocol = "rtsp",
                        PullParams = new DevicePullStreamParamModel()
                        {
                            UserName = request.UserName,
                            Password = request.Password,
                            Port = 554
                        },
                        StreamType = StreamTypes.Pull,
                        Enabled = true
                    },
                    DeviceStreamUrls = new List<NameValueObject>()
                };

                results.Add(result);

                var capabilities = await _onvifDeviceRequestProxy.GetDeviceCapabilities(deviceIp, request.UserName, request.Password);
                if (capabilities.IsEmpty())
                {
                    continue;
                }

                capabilities.TryGetValue("Media", out var mediaCapabilities);
                if (mediaCapabilities.IsEmpty())
                {
                    continue;
                }

                foreach (var capability in mediaCapabilities)
                {
                    // MediaService GetProfiles => 获取token , 一个token 一个流
                    var profiles = await _onvifDeviceRequestProxy.GetDeviceProfiles(deviceIp, request.UserName, request.Password, capability.Name, capability.Value);
                    if (profiles.IsEmpty())
                    {
                        continue;
                    }

                    foreach (var profile in profiles)
                    {
                        // Console.WriteLine($"token:{token}");
                        _logger.LogWarning($"token:{profile.Value}");
                        // MediaService GetStreamUri
                        var streamUrl = await _onvifDeviceRequestProxy.GetDeviceStreamUri(deviceIp, request.UserName, request.Password, profile.Value, capability.Name, capability.Value);
                        if (streamUrl.HasValues())
                        {
                            // Console.WriteLine($"streamUrl:{streamUrl}");
                            _logger.LogWarning($"streamUrl:{streamUrl}");
                            result.DeviceStreamUrls.Add(new NameValueObject()
                            {
                                Name = profile.Name,
                                Value = streamUrl
                            });
                        }
                    }
                }


            }

            return results;
        }

        public async Task<OperateResult> SendDevicePTZControl(OnvifDevicePTZControlRequestModel request)
        {
            var capabilities = await _onvifDeviceRequestProxy.GetDeviceCapabilities(request.RemoteIP, request.UserName, request.Password);
            if (capabilities.IsEmpty())
            {
                return OperateResult.Failed("获取设备PTZ功能失败");
            }

            capabilities.TryGetValue("Media", out var mediaCapabilities);
            if (mediaCapabilities.IsEmpty())
            {
                return OperateResult.Failed("获取设备PTZ功能失败");
            }

            capabilities.TryGetValue("PTZ", out var ptzCapabilities);
            if (ptzCapabilities.IsEmpty())
            {
                return OperateResult.Failed("设备不支持PTZ功能");
            }

            var mediaCapability = mediaCapabilities.First();
            var ptzCapability = ptzCapabilities.First();

            // MediaService GetProfiles => 获取token , 一个token 一个流
            var profiles = await _onvifDeviceRequestProxy.GetDeviceProfiles(request.RemoteIP, request.UserName, request.Password, mediaCapability.Name, mediaCapability.Value);
            if (profiles.IsEmpty())
            {
                return OperateResult.Failed("设备PTZ功能授权失败");
            }

            foreach (var profile in profiles)
            {
                // Console.WriteLine($"token:{token}");
                _logger.LogWarning($"token:{profile.Value}");
                // MediaService GetStreamUri
                var streamUrl = await _onvifDeviceRequestProxy.PTZContinuousMove(request.RemoteIP, request.UserName, request.Password, profile.Value, mediaCapability.Name, ptzCapability.Value, 0.5, 0.5, 0.5);

                // Console.WriteLine($"streamUrl:{streamUrl}");
                _logger.LogWarning($"streamUrl:{streamUrl}");
            }

            return OperateResult.Success;
        }

        public async Task<IEnumerable<PresetItemResponseModel>> GetPresets(OnvifDevicePTZControlRequestModel request)
        {
            var capabilities = await _onvifDeviceRequestProxy.GetDeviceCapabilities(request.RemoteIP, request.UserName, request.Password);
            if (capabilities.IsEmpty())
            {
                return Enumerable.Empty<PresetItemResponseModel>();
            }

            capabilities.TryGetValue("Media", out var mediaCapabilities);
            if (mediaCapabilities.IsEmpty())
            {
                return Enumerable.Empty<PresetItemResponseModel>();
            }

            capabilities.TryGetValue("PTZ", out var ptzCapabilities);
            if (ptzCapabilities.IsEmpty())
            {
                return Enumerable.Empty<PresetItemResponseModel>();
            }

            var mediaCapability = mediaCapabilities.First();
            var ptzCapability = ptzCapabilities.First();

            // MediaService GetProfiles => 获取token , 一个token 一个流
            var profiles = await _onvifDeviceRequestProxy.GetDeviceProfiles(request.RemoteIP, request.UserName, request.Password, mediaCapability.Name, mediaCapability.Value);
            if (profiles.IsEmpty())
            {
                return Enumerable.Empty<PresetItemResponseModel>();
            }

            var profile = profiles.First();

            // Console.WriteLine($"token:{token}");
            _logger.LogWarning($"token:{profile.Value}");
            // MediaService GetStreamUri
            return await _onvifDeviceRequestProxy.GetPresets(request.RemoteIP, request.UserName, request.Password, profile.Value, mediaCapability.Name, ptzCapability.Value);

            // Console.WriteLine($"streamUrl:{streamUrl}");
            // _logger.LogWarning($"streamUrl:{streamUrl}");            
        }

        public async Task<OperateResult> GotoPresets(OnvifDevicePTZPresetGotoRequestModel request)
        {
            var capabilities = await _onvifDeviceRequestProxy.GetDeviceCapabilities(request.RemoteIP, request.UserName, request.Password);
            if (capabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            capabilities.TryGetValue("Media", out var mediaCapabilities);
            if (mediaCapabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            capabilities.TryGetValue("PTZ", out var ptzCapabilities);
            if (ptzCapabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            var mediaCapability = mediaCapabilities.First();
            var ptzCapability = ptzCapabilities.First();

            // MediaService GetProfiles => 获取token , 一个token 一个流
            var profiles = await _onvifDeviceRequestProxy.GetDeviceProfiles(request.RemoteIP, request.UserName, request.Password, mediaCapability.Name, mediaCapability.Value);
            if (profiles.IsEmpty())
            {
                return OperateResult.Failed();
            }

            var profile = profiles.First();

            // Console.WriteLine($"token:{token}");
            _logger.LogWarning($"token:{profile.Value}");
            // MediaService GetStreamUri
            return await _onvifDeviceRequestProxy.GotoPresets(request.RemoteIP, request.UserName, request.Password, profile.Value, mediaCapability.Name, ptzCapability.Value, request.PresetToken);
        }


        public async Task<OperateResult> SetPresets(OnvifDevicePTZPresetSetRequestModel request)
        {
            var capabilities = await _onvifDeviceRequestProxy.GetDeviceCapabilities(request.RemoteIP, request.UserName, request.Password);
            if (capabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            capabilities.TryGetValue("Media", out var mediaCapabilities);
            if (mediaCapabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            capabilities.TryGetValue("PTZ", out var ptzCapabilities);
            if (ptzCapabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            var mediaCapability = mediaCapabilities.First();
            var ptzCapability = ptzCapabilities.First();

            // MediaService GetProfiles => 获取token , 一个token 一个流
            var profiles = await _onvifDeviceRequestProxy.GetDeviceProfiles(request.RemoteIP, request.UserName, request.Password, mediaCapability.Name, mediaCapability.Value);
            if (profiles.IsEmpty())
            {
                return OperateResult.Failed();
            }

            var profile = profiles.First();

            // Console.WriteLine($"token:{token}");
            _logger.LogWarning($"token:{profile.Value}");
            // MediaService GetStreamUri
            return await _onvifDeviceRequestProxy.SetPresets(request.RemoteIP, request.UserName, request.Password, profile.Value, mediaCapability.Name, ptzCapability.Value, request.PresetName, request.PresetToken);

            // Console.WriteLine($"streamUrl:{streamUrl}");
            // _logger.LogWarning($"streamUrl:{streamUrl}");            
        }


        public async Task<OperateResult> RemovePresets(OnvifDevicePTZPresetRemoveRequestModel request)
        {
            var capabilities = await _onvifDeviceRequestProxy.GetDeviceCapabilities(request.RemoteIP, request.UserName, request.Password);
            if (capabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            capabilities.TryGetValue("Media", out var mediaCapabilities);
            if (mediaCapabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            capabilities.TryGetValue("PTZ", out var ptzCapabilities);
            if (ptzCapabilities.IsEmpty())
            {
                return OperateResult.Failed();
            }

            var mediaCapability = mediaCapabilities.First();
            var ptzCapability = ptzCapabilities.First();

            // MediaService GetProfiles => 获取token , 一个token 一个流
            var profiles = await _onvifDeviceRequestProxy.GetDeviceProfiles(request.RemoteIP, request.UserName, request.Password, mediaCapability.Name, mediaCapability.Value);
            if (profiles.IsEmpty())
            {
                return OperateResult.Failed();
            }

            var profile = profiles.First();

            // Console.WriteLine($"token:{token}");
            _logger.LogWarning($"token:{profile.Value}");
            // MediaService GetStreamUri
            return await _onvifDeviceRequestProxy.RemovePresets(request.RemoteIP, request.UserName, request.Password, profile.Value, mediaCapability.Name, ptzCapability.Value, request.PresetToken);

            // Console.WriteLine($"streamUrl:{streamUrl}");
            // _logger.LogWarning($"streamUrl:{streamUrl}");            
        }
    }
}
